package com.atguigu.gmall.web.all.service.impl;

import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.cart.CartFeignClient;
import com.atguigu.gmall.feign.product.SkuInfoFeignClient;
import com.atguigu.gmall.feign.user.UserFeignClient;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.web.all.service.OrderService;
import net.sf.jsqlparser.statement.select.KSQLWindow;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author dyqstart
 * @create 2021-08-20-19:01
 * @since 1.0.0
 */
@Component
public class OrderServiceImpl implements OrderService {

    @Autowired
    CartFeignClient cartFeignClient;

    @Autowired
    UserFeignClient userFeignClient;

    @Autowired
    SkuInfoFeignClient skuInfoFeignClient;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Override
    public Map<String, Object> getOrderConfirmInfo(String userId) {
        HashMap<String, Object> map = new HashMap<>();
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        //多线程要操作，使用AtomicInteger 防止并发，必须不可变
        final BigDecimal[] totalAmount = {new BigDecimal("0.0")};
        final AtomicInteger[] totalNum = {new AtomicInteger(0)};

        //1、TODO 远程查询购物车服务，获取到购物车选中的所有商品列表
        CompletableFuture<List<CartInfo>> listCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //每个人，调用了feign拦截器，因此要自己异步线程将老请求放入，解决feign异步请求丢失问题
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<CartInfo> detailArrayList = cartFeignClient.getCartInfoListCheck();
            return detailArrayList;
        });

        //2、TODO 计算总价
        CompletableFuture<List<CartInfo>> totalAmountFuture = listCompletableFuture.whenCompleteAsync((result, execption) -> {
            List<CartInfo> infos = new ArrayList<>();
            for (CartInfo cartInfo : result) {
                //总价 = 数量 * 单价
                Integer skuNum = cartInfo.getSkuNum();
                totalNum[0].addAndGet(cartInfo.getSkuNum());//叠加数量
                RequestContextHolder.setRequestAttributes(requestAttributes);
                BigDecimal skuPrice = skuInfoFeignClient.getSkuPrice(cartInfo.getSkuId());
                cartInfo.setOrderPrice(skuPrice);
                BigDecimal multiply = skuPrice.multiply(new BigDecimal(skuNum.toString()));
                totalAmount[0] = totalAmount[0].add(multiply);

                infos.add(cartInfo);
            }

            map.put("detailArrayList",infos);
            map.put("totalNum",totalNum[0]);
            map.put("totalAmount",totalAmount[0]);
        });

        //3、TODO 远程查询用户的所有收货地址列表
        CompletableFuture<List<UserAddress>> addressFuture = CompletableFuture.supplyAsync(() -> {
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<UserAddress> address = userFeignClient.getCurrentUserAddress();
            map.put("userAddressList",address);
            return address;
        });

        //4、 TODO 页面需要tradeNo,页面用来做防重复提交
        CompletableFuture<Void> tokenFuture = CompletableFuture.runAsync(() -> {
            //存入后台防重复令牌
            String token = UUID.randomUUID().toString().replace("-", "");
            redisTemplate.opsForValue().set(RedisConst.USER_UNREPEAT_TOKEN + userId, token, RedisConst.USER_UNREPEAT_TOKEN_TTL, TimeUnit.SECONDS);
            map.put("tradeNo", token);
        });


//        CompletableFuture<Void> future = CompletableFuture
//                .allOf(listCompletableFuture, totalAmountFuture, addressFuture, tokenFuture);
//        future.get();

        CompletableFuture
                .allOf(listCompletableFuture, totalAmountFuture, addressFuture, tokenFuture)
                .join();

        //model.addAttribute("detailArrayList",null);
//        model.addAttribute("totalNum",null);  //orderPrice
//        model.addAttribute("totalAmount",null);
//        model.addAttribute("userAddressList",null);
//        model.addAttribute("tradeNo","dsajlkdjalkjd");

        return map;
    }
}
